from django.db import transaction
from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo,OrderGoods
from django.utils import timezone
from decimal import Decimal
from django_redis import get_redis_connection
class OrderPlaceSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1,label="数量")
    class Meta:
        model = SKU
        fields = ("default_image_url","name","price","count","id")


class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ("address","pay_method","order_id")

        read_only_fields = ["order_id"] #序列化的时候,(也就是返回的时候用,反序列化的时候不用)

        #write_only, 反序列化的时候用, 序列化的时候不用
        extra_kwargs = {
            "address":{
                "write_only":True
            },
            "pay_method":{
                "write_only":True
            }
        }

    #1,重写create方法,去出redis数据,创建订单对象, 订单商品对象
    @transaction.atomic
    def create(self, validated_data):

        #1,获取user
        user = self.context["request"].user

        #2,创建订单编号(尽量保证唯一性)
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d"%user.id

        #3,获取地址
        address = validated_data["address"]

        #4,获取支付方式
        pay_method = validated_data["pay_method"]

        #5,订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        # TODO 设置保存点
        sid = transaction.savepoint()

        #6,创建订单信息对象
        order = OrderInfo.objects.create(
            order_id = order_id,
            user = user,
            address = address,
            total_count = 0,
            total_amount = Decimal(0.0),
            freight = Decimal(10.0),
            pay_method = pay_method,
            status = status,
        )

        #7,获取redis中数据
        redis_conn = get_redis_connection("cart")
        cart_dict = redis_conn.hgetall("cart_%s"%user.id)
        cart_selected_list = redis_conn.smembers("cart_selected_%s"%user.id)

        #8,遍历创建订单商品对象
        for sku_id in cart_selected_list:
            # 添加循环
            while True:

                #8.1获取商品对象,数量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                #8.2判断库存量是否足够
                if count > sku.stock:
                    # TODO 设置回滚点
                    transaction.savepoint_rollback(sid)
                    raise serializers.ValidationError("库存不足")

                # 8.3减少库存,增加销量 TODO 使用乐观锁解决并发下单问题
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count  # 库存操作
                new_sales = old_sales + count  # 销量操作


                # sku.save()  #
                ret = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                # 使用商品对象查询id为商品id以及库存没有发生改变的情况下,订单成立,更新库存以及销量
                # ret 返回值是更新的数据的行数,如果没有发生改变则为0
                if ret == 0:
                    # raise serializers.ValidationError("下单失败")

                    continue  # 条件成立时,直接重新循环一次执行过的while True循环

                #8.4累加商品数量和价格
                order.total_count += count
                order.total_amount += (sku.price * count)

                #8.5创建订单商品对象
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )
                break
        #9,保存,清除redis数据
        order.save()
        # TODO 设置事物提交点
        transaction.savepoint_commit(sid)
        redis_conn.hdel("cart_%s"%user.id,*cart_selected_list)
        redis_conn.srem("cart_selected_%s"%user.id,*cart_selected_list)

        #10,返回响应
        return order

class SkuSrializer(serializers.ModelSerializer):
    class Meta:
        model = SKU
        fields = ("default_image_url","name")  # 商品图片,商品名字

class SkusSerializer(serializers.ModelSerializer):
    sku = SkuSrializer(read_only=True)
    class Meta:
        model = OrderGoods
        fields = ("sku","count","price")  # 商品,数量,单价,支付方式

class UserOrderInfoSerializer(serializers.ModelSerializer):

    skus = SkusSerializer(many=True, read_only=True)
    class Meta:
        model = OrderInfo
        fields = ("create_time","order_id","total_amount","freight","pay_method","skus","status")


    # 前段需要的数据
        # order
        # {
        #     create_time: create_time
        #     order_id: order_id
        #     skus: {
        #        sku: {
        #             default_image_url
        #         name
        #     }
        #
        #     price
        #         count
        #     amount
        # }
        # total_amount: total_amount
        # freight: freight
        # pay_method_name:
        # }
        #